import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, classification_report, ConfusionMatrixDisplay

# 1. 加载 MNIST 数据集
mnist = fetch_openml('mnist_784', version=1, as_frame=False, parser='auto')
X, y = mnist.data, mnist.target.astype(np.uint8)  # (70000, 784), 目标值转整数

# 2. 数据预处理（归一化 & 训练集划分）
X = X.astype(np.float32) / 255.0  # 先转换为 float32，再归一化  # 归一化到 [0,1]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)


# 3. 训练 SVM 模型（RBF 核）
svm_model = SVC(kernel='rbf', C=10, gamma=0.01)  # 选择适合的 C 和 gamma
# from sklearn.svm import LinearSVC
# svm_model = LinearSVC(C=1.0, max_iter=1000, dual=False)  # dual=False 适用于大数据
svm_model.fit(X_train, y_train)

# 4. 预测
y_pred = svm_model.predict(X_test)

# 5. 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"测试集准确率: {accuracy:.4f}")

# 6. 分类报告
print("\n分类报告:")
print(classification_report(y_test, y_pred))

# 7. 可视化部分预测错误的图片
misclassified = np.where(y_pred != y_test)[0]  # 获取错误分类的索引
fig, axes = plt.subplots(2, 5, figsize=(10, 5))
for i, ax in enumerate(axes.flat):
    idx = misclassified[i]
    ax.imshow(X_test[idx].reshape(28, 28), cmap='gray')
    ax.set_title(f"Pred: {y_pred[idx]}\nTrue: {y_test[idx]}")
    ax.axis("off")
plt.show()

# 8. 绘制混淆矩阵
ConfusionMatrixDisplay.from_estimator(svm_model, X_test, y_test, cmap="Blues")
plt.show()